package club.kynb.mall.application.listener;

import club.kynb.mall.application.config.AuthConfig;
import club.kynb.mall.application.config.AuthProperties;
import club.kynb.mall.application.limiter.AuthFailedCountLimiter;
import club.kynb.mall.application.model.model.command.LogoutCommand;
import club.kynb.mall.application.model.model.event.AuthFailedEvent;
import club.kynb.mall.application.model.model.event.AuthSuccessEvent;
import club.kynb.mall.application.model.model.event.UserPwdUpdateEvent;
import club.kynb.mall.application.service.AuthenticationApplicationService;
import club.kynb.mall.user.api.IUserService;
import club.kynb.mall.user.model.dto.UserDTO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.pizza.common.web.exception.Errors;
import org.pizza.event.annotation.AsyncEventListener;
import org.springframework.stereotype.Component;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author kynb_club@163.com
 * @since 2020/12/25 2:01 下午
 */
@Slf4j
@Component
@AllArgsConstructor
public class UserEventListener {
    private final AuthFailedCountLimiter authFailedCountLimiter;
    private final AuthProperties authProperties;
    private final IUserService iUserService;
    private final AuthenticationApplicationService authenticationApplicationService;

    @AsyncEventListener
    public void onAuthFailedEvent(AuthFailedEvent event) {
        Optional<AuthConfig> authConfig = authProperties.get(event.getClientType());
        AuthConfig config = authConfig.orElseThrow(() -> Errors.BIZ.exception("丢失对应客户端类型的认证配置"));
        //增加认证失败累加次数
        authFailedCountLimiter.increment(event.getPhone()
                , config.getFailedCount()
                , config.getWatchTime()
                , config.getLockedTime()
                , TimeUnit.MINUTES);
        log.info("登录失败事件处理器 >>>");
    }

    @AsyncEventListener
    public void onAuthSuccessEvent(AuthSuccessEvent event) {
        final UserDTO userDTO = new UserDTO();
        userDTO.setId(event.getUserId());
        userDTO.setCurrentToken(event.getToken());
        iUserService.loginSuccess(userDTO);
    }

    @AsyncEventListener
    public void onUserPwdUpdateEvent(UserPwdUpdateEvent event) {
        authenticationApplicationService.logout(new LogoutCommand().setToken(event.getToken()));
    }
}
